﻿// Copyright (c) MASA Stack All rights reserved.
// Licensed under the Apache License. See LICENSE.txt in the project root for license information.

using Masa.Auth.Contracts.Admin.DynamicRoles;
using Masa.Auth.Domain.DynamicRoles.Aggregates;

namespace Masa.Auth.Service.Admin.Infrastructure;

public static class MapsterAdapterConfig
{
    public static void TypeAdapter()
    {
        TypeAdapterConfig.GlobalSettings.Default.MapToConstructor(true);

        TypeAdapterConfig<string, ClientGrantType>.NewConfig().MapWith(src => new ClientGrantType(src));
        TypeAdapterConfig<string, ClientRedirectUri>.NewConfig().MapWith(src => new ClientRedirectUri(src));
        TypeAdapterConfig<string, ClientPostLogoutRedirectUri>.NewConfig().MapWith(src => new ClientPostLogoutRedirectUri(src));
        TypeAdapterConfig<string, ClientScope>.NewConfig().MapWith(src => new ClientScope(src));
        TypeAdapterConfig<string, ClientCorsOrigin>.NewConfig().MapWith(src => new ClientCorsOrigin(src));
        TypeAdapterConfig<ClientGrantType, string>.NewConfig().MapWith(src => src.GrantType);
        TypeAdapterConfig<ClientRedirectUri, string>.NewConfig().MapWith(src => src.RedirectUri);
        TypeAdapterConfig<ClientPostLogoutRedirectUri, string>.NewConfig().MapWith(src => src.PostLogoutRedirectUri);
        TypeAdapterConfig<ClientScope, string>.NewConfig().MapWith(src => src.Scope);
        TypeAdapterConfig<ClientCorsOrigin, string>.NewConfig().MapWith(src => src.Origin);

        TypeAdapterConfig<DateOnly?, DateTime?>.NewConfig().MapWith(src => src.HasValue ? src.Value.ToDateTime(TimeOnly.Parse("00:00")) : null);
        TypeAdapterConfig<DateTime?, DateOnly?>.NewConfig().MapWith(src => src.HasValue ? DateOnly.FromDateTime(src.Value) : null);
        TypeAdapterConfig<string, ClientGrantType>.NewConfig().MapWith(item => new ClientGrantType(item));
        //TypeAdapterConfig<ClientDetailDto, Client>.NewConfig().IgnoreIf((src, dest) => dest.AllowedScopes.Any(), dest => dest.AllowedScopes);

        TypeAdapterConfig<LdapDetailDto, LdapOptions>.ForType()
            .Map(dest => dest.ServerPort, src => src.IsLdaps ? 0 : src.ServerPort)
            .Map(dest => dest.ServerPortSsl, src => src.IsLdaps ? src.ServerPort : 0);

        TypeAdapterConfig<User, CacheUser>.NewConfig().Map(cache => cache.Roles, user => user.Roles.Select(role => role.RoleId).ToList());
        TypeAdapterConfig<User, UserModel>.NewConfig().Map(user => user.Roles, user => user.Roles.Select(ur => new RoleModel
        {
            Id = ur.RoleId,
            Code = ur.Role == null ? "" : ur.Role.Code,
            Name = ur.Role == null ? "" : ur.Role.Name,
        }).ToList());

        TypeAdapterConfig<ThirdPartyIdp, ThirdPartyIdpModel>.ForType()
            .Map(item => item.JsonKeyMap, item => JsonSerializer.Deserialize<Dictionary<string, string>>(string.IsNullOrEmpty(item.JsonKeyMap) ? "{}" : item.JsonKeyMap, new JsonSerializerOptions()));
        TypeAdapterConfig<ThirdPartyIdp, ThirdPartyIdpDetailDto>.ForType()
            .Map(item => item.JsonKeyMap, item => JsonSerializer.Deserialize<Dictionary<string, string>>(string.IsNullOrEmpty(item.JsonKeyMap) ? "{}" : item.JsonKeyMap, new JsonSerializerOptions()));

        TypeAdapterConfig<AuthenticationDefaults, ThirdPartyIdpModel>.ForType()
            .Map(item => item.Name, item => item.Scheme);

        TypeAdapterConfig<Permission, CachePermission>.NewConfig().Map(cache => cache.ApiPermissions, permission => permission.AffiliationPermissionRelations.Select(p => p.AffiliationPermissionId));

        TypeAdapterConfig<DynamicRoleUpsertDto, DynamicRole>.NewConfig()
            .MapToConstructor(true)
            .Map(dest => dest.Conditions, src =>
                src.Conditions.Select((dto, index) => new DynamicRuleCondition(
                    dto.LogicalOperator,
                    dto.FieldName,
                    Enumeration.FromValue<OperatorType>((int)dto.OperatorType),
                    dto.Value,
                     Enumeration.FromValue<DynamicRoleDataType>((int)dto.DataType),
                    index)).ToList())
            .Map(dest => dest.ControlPolicies, src =>
                src.ControlPolicies.Select(dto => new ControlPolicy
                {
                    Name = dto.Name,
                    Effect = Enumeration.FromValue<Masa.Auth.Domain.DynamicRoles.Aggregates.StatementEffect>((int)dto.Effect),
                    Priority = dto.Priority,
                    Enabled = dto.Enabled,
                    Actions = dto.Actions.Select(actionDto => new ActionIdentifier(actionDto.ToString())).ToList(),
                    Resources = dto.Resources.Select(resourceDto => new ResourceIdentifier(resourceDto.ToString())).ToList()
                }).ToList());
        TypeAdapterConfig<DynamicRuleConditionDto, DynamicRuleCondition>.NewConfig().MapToConstructor(true).Map(dest => dest.OperatorType, src => Enumeration.FromValue<OperatorType>((int)src.OperatorType));

        TypeAdapterConfig<OperatorType, OperatorTypes>.NewConfig().MapWith(src => (OperatorTypes)src.Id);
        TypeAdapterConfig<OperatorTypes, OperatorType>.NewConfig().MapWith(src => Enumeration.FromValue<OperatorType>((int)src));
        TypeAdapterConfig<DynamicRoleDataType, DynamicRoleDataTypes>.NewConfig().MapWith(src => (DynamicRoleDataTypes)src.Id);
        TypeAdapterConfig<DynamicRoleDataTypes, DynamicRoleDataType>.NewConfig().MapWith(src => Enumeration.FromValue<DynamicRoleDataType>((int)src));

        // StatementEffect 枚举映射配置
        TypeAdapterConfig<Masa.Auth.Domain.DynamicRoles.Aggregates.StatementEffect, Masa.Auth.Contracts.Admin.DynamicRoles.StatementEffect>.NewConfig()
            .MapWith(src => (Masa.Auth.Contracts.Admin.DynamicRoles.StatementEffect)src.Id);
            
        // StatementEffect 反向映射配置
        TypeAdapterConfig<Masa.Auth.Contracts.Admin.DynamicRoles.StatementEffect, Masa.Auth.Domain.DynamicRoles.Aggregates.StatementEffect>.NewConfig()
            .MapWith(src => Enumeration.FromValue<Masa.Auth.Domain.DynamicRoles.Aggregates.StatementEffect>((int)src));

        // ControlPolicy 映射配置
        TypeAdapterConfig<ControlPolicy, ControlPolicyDto>.NewConfig()
            .Map(dest => dest.Actions, src => src.Actions.Select(action => new ActionIdentifierDto(action.ToString())).ToList())
            .Map(dest => dest.Resources, src => src.Resources.Select(resource => new ResourceIdentifierDto(resource.ToString())).ToList());
            
        // ControlPolicyDto 到 ControlPolicy 的反向映射配置
        TypeAdapterConfig<ControlPolicyDto, ControlPolicy>.NewConfig()
            .Map(dest => dest.Id, src => Guid.Empty) // 忽略 DTO 中的 Id，让 EF Core 自动生成
            .Map(dest => dest.Actions, src => src.Actions.Select(actionDto => new ActionIdentifier(actionDto.ToString())).ToList())
            .Map(dest => dest.Resources, src => src.Resources.Select(resourceDto => new ResourceIdentifier(resourceDto.ToString())).ToList());
        
        TypeAdapterConfig<ActionIdentifier, ActionIdentifierDto>.NewConfig()
            .MapWith(src => new ActionIdentifierDto(src.ToString()));
            
        TypeAdapterConfig<ResourceIdentifier, ResourceIdentifierDto>.NewConfig()
            .MapWith(src => new ResourceIdentifierDto(src.ToString()));
    }
}
